from django.db.models import Q, F
from rest_framework import mixins, status
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.decorators import action

from drf_yasg.utils import swagger_auto_schema

from api.auth import JWTAuthentication, User
from api.models import Basket, Porduct, BasketLine
from api.routes.basket.serializer import (
    BasketIdSerializer,
    BasketDataSerializer,
    BasketQeuryListSerializer,
    BasketLineQeurySerializer,
    BasketLineIdSerializer,
    BasketBodySerializer,
    DeleteBasketLineBodySerializer,
)
from api.utils.common import with_common_response, paginate_list
from api.utils.enums import BasketType


class BasketViewSet(viewsets.ViewSet):

    permission_classes = [JWTAuthentication]

    @swagger_auto_schema(
        operation_summary="创建购物车",
        operation_description="创建购物车",
        responses=with_common_response({status.HTTP_200_OK: BasketIdSerializer}),
    )
    def create(self, request):

        basket, _ = Basket.objects.update_or_create(
            user=request.user, defaults={"status": BasketType.PRE.value}
        )

        response = BasketIdSerializer(basket)

        return Response(status=status.HTTP_201_CREATED, data=response.data)

    @swagger_auto_schema(
        operation_summary="更新购物车",
        operation_description="更新购物车",
        request_body=BasketLineQeurySerializer,
        responses=with_common_response({status.HTTP_200_OK: BasketLineIdSerializer}),
    )
    def update(self, request, pk):
        serializer = BasketLineQeurySerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            product_id = serializer.validated_data.get("product_id")
            quantity = serializer.validated_data.get("quantity", 1)
            pay_type = serializer.validated_data.get("pay_type")
            basket_status = serializer.validated_data.get("status")
            address = serializer.validated_data.get("address")
            choice = serializer.validated_data.get("choice")

            query_body = {}
            if quantity:
                query_body.update({"quantity": quantity})
            if pay_type:
                query_body.update({"pay_type": pay_type})
            if choice is not None:
                query_body.update({"choice": choice})

            # 查询指定购物车
            try:
                basket = Basket.objects.get(id=pk)
            except Exception as e:
                raise RecursionError

            # 查询产品
            if product_id:
                try:
                    product = Porduct.objects.get(
                        product_id=product_id,
                    )
                except Exception as e:
                    raise RecursionError

                # 查询库存价格
                stock_record = product.stock_record.first()
                stock_pirce = stock_record.price.get(type=pay_type)

                query_body.update({"basket": basket})
                if product in BasketLine.objects.values_list("product", flat=True):
                    query_body.update({"price": stock_pirce.price * F("quantity")})
                else:
                    query_body.update({"price": stock_pirce.price * int(quantity)})
                # 添加商品到basket_line

                basket_line, _ = BasketLine.objects.update_or_create(
                    product=product, defaults=query_body
                )

            # 更新购物车状态
            basket.status = basket_status
            basket.save()
            # 如果购物车状态是最终购物车那么就生成订单
            if basket.status == BasketType.FINAL.value:
                order = basket.make_order(address)
                # 如果订单生成就删除购物车
                if order is not None:
                    basket.delete()

            response = BasketLineIdSerializer(basket)

            return Response(status=status.HTTP_202_ACCEPTED, data=response.data)

    @swagger_auto_schema(
        operation_summary="购物车详情",
        operation_description="购物车详情",
        responses=with_common_response({status.HTTP_200_OK: BasketBodySerializer}),
    )
    def retrieve(self, request, pk):
        try:
            basket = Basket.objects.get(id=pk)
        except Exception as e:
            raise "未找到购物车"
        response = BasketBodySerializer(basket)

        return Response(status=status.HTTP_200_OK, data=response.data)

    @swagger_auto_schema(
        operation_summary="删除购物车商品",
        operation_description="删除购物车商品",
        request_body=DeleteBasketLineBodySerializer,
        responses=with_common_response({status.HTTP_200_OK: BasketIdSerializer}),
    )
    def destroy(self, request, pk):
        serializer = DeleteBasketLineBodySerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        product_ids = serializer.validated_data.get("product_ids")
        try:
            basket = Basket.objects.get(id=pk)
        except Exception as e:
            raise "未找到购物车"
        # 查询basketline并删除
        basket.basket_lines.filter(product__product_id__in=product_ids).delete()

        response = BasketBodySerializer(basket)

        return Response(status=status.HTTP_200_OK, data=response.data)


class AdminBasketViewSet(viewsets.ViewSet):
    @swagger_auto_schema(
        operation_summary="购物车列表",
        operation_description="购物车列表",
        query_serializer=BasketQeuryListSerializer,
        responses=with_common_response({status.HTTP_200_OK: BasketDataSerializer}),
    )
    @action(methods=["GET"], url_name="baskets", url_path="baskets", detail=False)
    def admin_basket_list(self, request):
        serializer = BasketQeuryListSerializer(data=request.GET)
        if serializer.is_valid(raise_exception=True):
            statues = serializer.validated_data.get("status")
            product_id = serializer.validated_data.get("product")
            pay_type = serializer.validated_data.get("pay_type")
            username = serializer.validated_data.get("username")
            page = serializer.validated_data.get("page")
            per_page = serializer.validated_data.get("per_page")
            limit = serializer.validated_data.get("limit")

            qeury_body = {}
            if statues:
                qeury_body.update({"status": statues})
            if product_id:
                qeury_body.update({"basket_lines__product__product_id": product_id})
            if pay_type:
                qeury_body.update({"basket_lines__product__stock_record__price__type": pay_type})
            if username:
                qeury_body.update({"user__username": username})

            baskets = Basket.objects.filter(**qeury_body)

            data, total = paginate_list(baskets, page, per_page, limit)

            response = BasketDataSerializer({"total": total, "data": data})

            return Response(status=status.HTTP_200_OK, data=response.data)
